昨天我們完成了,從Linebot收到檔案,並且上傳到Google Drive上的指定資料夾。
但是目前指定資料夾的ID是寫死的,我們也不可能每次要指定資料夾都去查一次FolderID,然後讓使用者手動輸入ID。加上目前顯示資料夾的方式也是直接用文字印出的,所以我們今天來刻個Flex Message,讓我們的介面美觀一點,並且一切操作都能透過按鈕完成。
首先,我們到Line官方提供的Flex Message Simulator,建立一個carousel,簡單拉出想像中的樣子,目前希望的設定大概如下:
大概拉出下面這樣子
接著我們透過網站直接將其導出成JSON,我們先放一個bubble就好。
{
"type": "carousel",
"contents": [
{
"type": "bubble",
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "FOLDER",
"weight": "bold",
"color": "#1DB446",
"size": "sm"
},
{
"type": "text",
"text": "Folder Name",
"weight": "bold",
"size": "xxl",
"margin": "md"
},
{
"type": "text",
"text": "/path/to/floder",
"size": "xs",
"color": "#aaaaaa",
"wrap": true
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "vertical",
"margin": "xxl",
"spacing": "sm",
"contents": [
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Folder1",
"size": "sm",
"color": "#555555",
"decoration": "underline",
"maxLines": 25,
"align": "start",
"margin": "none",
"gravity": "center",
"flex": 0
},
{
"type": "filler"
},
{
"type": "button",
"action": {
"type": "postback",
"label": "進入資料夾",
"data": "hello",
"displayText": "進入Folder1"
},
"style": "link",
"height": "sm",
"gravity": "center",
"flex": 0,
"adjustMode": "shrink-to-fit"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Folder2",
"size": "sm",
"color": "#555555",
"decoration": "underline",
"maxLines": 25,
"align": "start",
"margin": "none",
"gravity": "center",
"flex": 0
},
{
"type": "filler"
},
{
"type": "button",
"action": {
"type": "postback",
"label": "進入資料夾",
"data": "hello",
"displayText": "進入Folder2"
},
"style": "link",
"height": "sm",
"gravity": "center",
"flex": 0,
"adjustMode": "shrink-to-fit"
}
]
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "horizontal",
"margin": "xxl",
"contents": [
{
"type": "text",
"text": "Total Files",
"size": "sm",
"color": "#555555",
"flex": 0
},
{
"type": "text",
"text": "3",
"size": "sm",
"color": "#111111",
"align": "end"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "FILE1",
"size": "sm",
"color": "#555555"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "FILE2",
"size": "sm",
"color": "#555555"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "FILE3",
"size": "sm",
"color": "#555555"
}
]
}
]
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "horizontal",
"margin": "md",
"contents": [
{
"type": "button",
"action": {
"type": "postback",
"label": "設為上傳資料夾",
"data": "folderid"
},
"scaling": true,
"style": "primary",
"adjustMode": "shrink-to-fit"
}
]
}
]
},
"styles": {
"footer": {
"separator": true
}
}
},
{
"type": "bubble",
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "FOLDER",
"weight": "bold",
"color": "#1DB446",
"size": "sm"
},
{
"type": "text",
"text": "Folder Name",
"weight": "bold",
"size": "xxl",
"margin": "md"
},
{
"type": "text",
"text": "/path/to/floder",
"size": "xs",
"color": "#aaaaaa",
"wrap": true
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "vertical",
"margin": "xxl",
"spacing": "sm",
"contents": [
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Folder1",
"size": "sm",
"color": "#555555",
"decoration": "underline",
"maxLines": 25,
"align": "start",
"margin": "none",
"gravity": "center",
"flex": 0
},
{
"type": "filler"
},
{
"type": "button",
"action": {
"type": "postback",
"label": "進入資料夾",
"data": "hello",
"displayText": "進入Folder1"
},
"style": "link",
"height": "sm",
"gravity": "center",
"flex": 0,
"adjustMode": "shrink-to-fit"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Folder2",
"size": "sm",
"color": "#555555",
"decoration": "underline",
"maxLines": 25,
"align": "start",
"margin": "none",
"gravity": "center",
"flex": 0
},
{
"type": "filler"
},
{
"type": "button",
"action": {
"type": "postback",
"label": "進入資料夾",
"data": "hello",
"displayText": "進入Folder2"
},
"style": "link",
"height": "sm",
"gravity": "center",
"flex": 0,
"adjustMode": "shrink-to-fit"
}
]
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "horizontal",
"margin": "xxl",
"contents": [
{
"type": "text",
"text": "Total Files",
"size": "sm",
"color": "#555555",
"flex": 0
},
{
"type": "text",
"text": "3",
"size": "sm",
"color": "#111111",
"align": "end"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "FILE1",
"size": "sm",
"color": "#555555"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "FILE2",
"size": "sm",
"color": "#555555"
}
]
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "FILE3",
"size": "sm",
"color": "#555555"
}
]
}
]
},
{
"type": "separator",
"margin": "xxl"
},
{
"type": "box",
"layout": "horizontal",
"margin": "md",
"contents": [
{
"type": "button",
"action": {
"type": "postback",
"label": "設為上傳資料夾",
"data": "folderid"
},
"scaling": true,
"style": "primary",
"adjustMode": "shrink-to-fit"
}
]
}
]
},
"styles": {
"footer": {
"separator": true
}
}
}
]
}
下一步,我們到Callback加入新的條件來回傳我們建立的carousel。
接著最痛苦的時間來了,對照著上面的JSON,我們要用Go組出對應的結構,基本打上關鍵字VsCode會自動跳出對應的結構給你選,所以對著JSON打就好。
比較要注意的是有些字段都是要求接收指向Int的指標,像是Flex之類的,這時候可以直接用linebot.IntPtr()
來回傳指標。
下面有一些地方有IT邦有跑版,畢竟一堆縮排,複製到VSCode會比較清楚。
// internal\router\api\v1\callback.go
if message.Text == "flex carousel" {
contents := &linebot.CarouselContainer{
Type: linebot.FlexContainerTypeCarousel,
Contents: []*linebot.BubbleContainer{
{
Type: linebot.FlexContainerTypeBubble,
Body: &linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeVertical,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "FOLDER",
Weight: linebot.FlexTextWeightTypeBold,
Color: "#1DB446",
Size: linebot.FlexTextSizeTypeSm,
},
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "Folder Name",
Weight: linebot.FlexTextWeightTypeBold,
Size: linebot.FlexTextSizeTypeXxl,
Margin: linebot.FlexComponentMarginTypeMd,
},
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "/path/to/floder",
Size: linebot.FlexTextSizeTypeXs,
Color: "#aaaaaa",
Wrap: true,
},
&linebot.SeparatorComponent{
Type: linebot.FlexComponentTypeSeparator,
Margin: linebot.FlexComponentMarginTypeXxl,
},
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeVertical,
Margin: linebot.FlexComponentMarginTypeXxl,
Spacing: linebot.FlexComponentSpacingTypeSm,
Contents: []linebot.FlexComponent{
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "Folder1",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
Decoration: linebot.FlexTextDecorationTypeUnderline,
MaxLines: linebot.IntPtr(25),
Align: linebot.FlexComponentAlignTypeStart,
Margin: linebot.FlexComponentMarginTypeNone,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
},
&linebot.FillerComponent{
Type: linebot.FlexComponentTypeFiller,
},
&linebot.ButtonComponent{
Type: linebot.FlexComponentTypeButton,
Action: &linebot.PostbackAction{
Label: "進入資料夾",
Data: "folderid1",
DisplayText: "進入Folder1",
},
Style: linebot.FlexButtonStyleTypeLink,
Height: linebot.FlexButtonHeightTypeSm,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
AdjustMode: linebot.FlexComponentAdjustModeTypeShrinkToFit,
},
},
},
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "Folder2",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
Decoration: linebot.FlexTextDecorationTypeUnderline,
MaxLines: linebot.IntPtr(25),
Align: linebot.FlexComponentAlignTypeStart,
Margin: linebot.FlexComponentMarginTypeNone,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
},
&linebot.FillerComponent{
Type: linebot.FlexComponentTypeFiller,
},
&linebot.ButtonComponent{
Type: linebot.FlexComponentTypeButton,
Action: &linebot.PostbackAction{
Label: "進入資料夾",
Data: "folderid2",
DisplayText: "進入Folder2",
},
Style: linebot.FlexButtonStyleTypeLink,
Height: linebot.FlexButtonHeightTypeSm,
Gravity: linebot.FlexComponentGravityTypeCenter,
Flex: linebot.IntPtr(0),
AdjustMode: linebot.FlexComponentAdjustModeTypeShrinkToFit,
},
},
},
},
},
// Separator
&linebot.SeparatorComponent{
Margin: linebot.FlexComponentMarginTypeXxl,
},
// Files
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Margin: linebot.FlexComponentMarginTypeXxl,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "Total Files",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
Flex: linebot.IntPtr(0),
},
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "3",
Size: linebot.FlexTextSizeTypeSm,
Color: "#111111",
Align: linebot.FlexComponentAlignTypeEnd,
},
},
},
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "FILE1",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
},
},
},
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "FILE2",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
},
},
},
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Contents: []linebot.FlexComponent{
&linebot.TextComponent{
Type: linebot.FlexComponentTypeText,
Text: "FILE3",
Size: linebot.FlexTextSizeTypeSm,
Color: "#555555",
},
},
},
// Separator
&linebot.SeparatorComponent{
Margin: linebot.FlexComponentMarginTypeXxl,
},
// Button
&linebot.BoxComponent{
Type: linebot.FlexComponentTypeBox,
Layout: linebot.FlexBoxLayoutTypeHorizontal,
Margin: linebot.FlexComponentMarginTypeMd,
Contents: []linebot.FlexComponent{
&linebot.ButtonComponent{
Type: linebot.FlexComponentTypeButton,
Action: &linebot.PostbackAction{
Label: "設為上傳資料夾",
Data: "folderid",
DisplayText: "設為上傳資料夾",
},
Style: linebot.FlexButtonStyleTypePrimary,
AdjustMode: linebot.FlexComponentAdjustModeTypeShrinkToFit,
},
},
},
},
},
Styles: &linebot.BubbleStyle{
Footer: &linebot.BlockStyle{
Separator: true,
},
},
},
},
}
if _, err := app.LineBotClient.ReplyMessage(
event.ReplyToken,
linebot.NewFlexMessage("Flex message alt text", contents),
).Do(); err != nil {
log.Println(err)
return
}
}
組完眼睛真的要花了,最後到Linebot上測試一下,可以看到組出來的效果應該是跟我們拉的一致 (如果沒有眼花的話XD) ,那我們今天就先到這兒,明天見~